// Copyright (C) 2009 Jesse Jones
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using MmmDoc;
using Mono.Cecil;
using System;
using System.Text;

namespace MmmDoc.Database
{
	/// <summary>Used for composite types like arrays and pointers.</summary>
	internal sealed class TypeSpec : TypeName
	{
		public TypeSpec(Document doc, TypeSpecification spec) : base(doc, spec)
		{
			ElementType = TypeName.Create(doc, spec.ElementType);
			
			MmmDoc.Database.SetSuffix.Invoke(this, spec);
		}
		
		public TypeName ElementType {get; private set;}
		
		/// <summary>&quot;[]&quot;, &quot;*&quot;, etc.</summary>
		public string Suffix {get; private set;}
		
		internal override string GetXmlName()
		{
			var builder = new System.Text.StringBuilder();
			
			builder.Append(ElementType.GetXmlName());
			builder.Append(Suffix);
			
			return builder.ToString();
		}
		
		#pragma warning disable 0169
		[SetSuffix.Overload]
		private void SetSuffix(PointerType spec)
		{
			Suffix = "*";
		}
		
		[SetSuffix.Overload]
		private void SetSuffix(ReferenceType spec)
		{
			Suffix = string.Empty;		// used for ref and out parameters
		}
		
		[SetSuffix.Overload]
		private void SetSuffix(ArrayType spec)
		{
			var builder = new StringBuilder();
			builder.Append("[");
			for (int i = 0; i < spec.Dimensions.Count; i++)
			{
				ArrayDimension dim = spec.Dimensions[i];
				string rank = dim.ToString();
				if (i < spec.Dimensions.Count - 1)
					builder.Append(",");
				if (rank.Length > 0)
				{
					builder.Append(" ");
					builder.Append(rank);
				}
			}
			builder.Append("]");
			
			Suffix = builder.ToString();
		}
		#pragma warning restore 0169
	}
}
